<?php

class PluginnahoWikiHistoryForm extends sfForm
{

  /**
   *
   * @var nahoWikiPage
   */
  protected $object;

  /**
   *
   * @param $revision
   * @param $options
   * @param $CSRFSecret
   * @return unknown_type
   */
  public function __construct(nahoWikiPage $page, $defaults = array(), $options = array(), $CSRFSecret = null)
  {
    sfApplicationConfiguration::getActive()->loadHelpers('I18N');

    $this->object = $page;

    parent::__construct($defaults, $options, $CSRFSecret);
  }

  /**
   * (non-PHPdoc)
   * @see vendor/symfony/lib/form/sfForm#setup()
   */
  public function setup()
  {
    $revisions = array('new' => $this->object->getLatestRevision(), 'old' => $this->object->getLatestRevision()-1);
    $this->setWidgets(array(
      'page'      => new sfWidgetFormInputHidden(array('default' => $this->object->getName())),
      'mode'      => new sfWidgetFormInputHidden(array('default' => 'inline')),
      'revision'  => new nahoWikiRevisionsWidget(array('default' => $revisions, 'page' => $this->object, 'label' => __('History'))),
      'submit'    => new sfWidgetFormInput(array('type' => 'submit', 'label' => '&nbsp;'), array('class' => 'submit-button', 'value' => __('View changes between selected versions'))),
    ));

    $this->setValidators(array(
      'page'     => new sfValidatorPass(),
      'mode'     => new sfValidatorPass(),
      'revision' => new sfValidatorPass(),
      'submit'   => new sfValidatorPass(),
    ));

    $this->widgetSchema->setNameFormat(sfConfig::get('app_nahoWikiPlugin_diff_form_name', 'wiki_diff').'[%s]');
  }

  /**
   *
   * @var array of nahoWikiRevision
   */
  protected $revisions = array();

  /**
   *
   * @return nahoWikiRevision
   */
  public function getRevision($type)
  {
    $revisions = $this->getValue('revision');
    if (!isset($revisions[$type]))
    {
      throw new Exception('Revision "'.$type.'" is not defined');
    }

    if (isset($this->revisions[$type]))
    {
      return $this->revisions[$type];
    }

    // Note : we do not make a query here, we just ask to page all its revisions (cached), as the history widget will retrieve them anyway
    $page_revisions = $this->object->getRevisions();
    foreach ($page_revisions as $page_revision)
    {
      if ($page_revision->getRevision() == $revisions[$type])
      {
        return $this->revisions[$type] = $page_revision;
      }
    }

    throw new Exception('Revision "'.$type.'" cannot be found');
  }

  /**
   *
   * @var Text_Diff
   */
  protected $diff = null;

  /**
   *
   * @return Text_Diff
   */
  public function getDiff()
  {
    if (!is_null($this->diff))
    {
      return $this->diff;
    }

    $lines1 = explode("\n", $this->getRevision('old')->getContent());
    $lines2 = explode("\n", $this->getRevision('new')->getContent());

    return $this->diff = new Text_Diff('auto', array($lines1, $lines2));
  }

  /**
   * Renders diff
   *
   * @param $mode e.g. "inline", "context", or "unified"
   * @return string
   */
  public function renderDiff($mode = 'inline')
  {
    $diff = $this->getDiff();

    $class = 'Text_Diff_Renderer_' . $mode;
    if (!class_exists($class))
    {
      throw new Exception('Invalid diff renderer "'.$mode.'" (class "'.$class.'" not found)');
    }

    $renderer = new $class();

    return $renderer->render($diff);
  }

}
